package gs.eisenhower.swallet.ui_component;

import gs.eisenhower.swallet.R;
import gs.eisenhower.swallet.dao.BudgetDao;
import gs.eisenhower.swallet.dao.BudgetDaoImpl;
import gs.eisenhower.swallet.dao.CategoryDao;
import gs.eisenhower.swallet.dao.CategoryDaoImpl;
import gs.eisenhower.swallet.dao.WalletDao;
import gs.eisenhower.swallet.dao.WalletDaoImpl;
import gs.eisenhower.swallet.factory.ModelFactory;
import gs.eisenhower.swallet.model.Budget;
import gs.eisenhower.swallet.model.Category;
import gs.eisenhower.swallet.model.Entity;
import gs.eisenhower.swallet.model.Wallet;
import gs.eisenhower.swallet.utility.ChartType;
import gs.eisenhower.swallet.utility.FinanceType;
import gs.eisenhower.swallet.utils.constants.WalletConstants;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.CategorySeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;


public class ReportsFragment extends Fragment {	
	private List<String> categories;
	private List<Double> amounts;
	private Map<String, Double> budget;
	private Map<String, GraphicalView> charts;
	private Integer[] colors;
	private String chartTitle;
	private LinearLayout layout;
	private ChartType currentChartType;
	private GraphicalView chartView;
	private WalletDao walletTransaction;
	private BudgetDao budgetTransaction;
	private CategoryDao categoryTransaction;
	
	 @Override
	 public View onCreateView(LayoutInflater inflater, ViewGroup container,
	                             Bundle savedInstanceState) {
	        return inflater.inflate(R.layout.fragment_reports, container, false);
	 }
	 
	@Override
	public void onActivityCreated (Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		
		walletTransaction   = new WalletDaoImpl();
		budgetTransaction   = new BudgetDaoImpl();
		categoryTransaction = new CategoryDaoImpl();
		
		budget = new HashMap<String, Double>();
		
		layout = (LinearLayout) getView().findViewById(R.id.reportLayout);
		charts = new HashMap<String, GraphicalView>();
		
		drawChart(ChartType.PieExpenditures);
		
		Button expendituresBtn = (Button) getView().findViewById(
				R.id.pieChartExpendituresButton);
		expendituresBtn.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				drawChart(ChartType.PieExpenditures);
			}
		});
		
		Button earningsBtn = (Button) getView().findViewById(
				R.id.pieChartEarningsButton);
		earningsBtn.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				drawChart(ChartType.PieEarnings);
			}
		});
		
		Button budgetBtn = (Button) getView().findViewById(
				R.id.lineChartButton);
		budgetBtn.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				drawChart(ChartType.LineEvolution);
			}
		});
	}
	
	@Override
	public void onResume() {
		super.onResume();
	}
	
	private void drawChart(ChartType chartType) {
		// Will not perform any draw operations if it's still same chart
		if (currentChartType == chartType)
			return;
		
		switch (chartType) {
		case PieExpenditures: {			
			chartTitle = "Expenditures per category";
			currentChartType = ChartType.PieExpenditures;
			Wallet expendituresWallet = new Wallet();
			expendituresWallet.setType(FinanceType.Expenditure.name());
			configurePieChart(expendituresWallet);
			
			if (categories.isEmpty()) {
				String title   = "No data to report";
				showAlertDialog(title, null);
			}
			break;
		}
		case PieEarnings: {
			chartTitle = "Earnings per category";
			currentChartType = ChartType.PieEarnings;
			Wallet earningsWallet = new Wallet();
			earningsWallet.setType(FinanceType.Earning.name());
			configurePieChart(earningsWallet);
			
			if (categories.isEmpty()) {
				String title   = "No data to report";
				showAlertDialog(title, null);
			}
			break;
		}
		case LineEvolution: {
			chartTitle = "Budget Evolution";
			currentChartType = ChartType.LineEvolution;
			configureLineChart((Budget) ModelFactory.getInstance().createModelInstance(
					Budget.class));
			
			if (budget.isEmpty()) {
				String title   = "No data to report";
				showAlertDialog(title, null);
			}
			break;
		}
		default:
			break;
		}
	}
	
	private void initColorPallete(int size) {
		Integer[] colorPallete = new Integer[] { Color.GREEN, Color.CYAN,
				Color.RED, Color.DKGRAY, Color.GRAY, Color.LTGRAY, Color.WHITE,
				Color.YELLOW, Color.BLUE, Color.MAGENTA };
		
		List<Integer> listOfColors = new ArrayList<Integer>(); 
		for (int i = 0; i < size; i++) {
			int colorIndex = i % colorPallete.length;
			listOfColors.add(colorPallete[colorIndex]);
		}
		colors = new Integer[listOfColors.size()];
		listOfColors.toArray(colors);
	}
	
	private void configurePieChart(Entity entity) {
		layout.removeAllViews();
		
		if (charts.containsKey(entity.getType())) {
			chartView = charts.get(entity.getType());
			layout.addView(chartView);
		} else {
			fetchDataForPieChart(entity);
			
			int numberOfColors = amounts.size();
			initColorPallete(numberOfColors);

			// Instantiating CategorySeries to plot Pie Chart
			CategorySeries distributionSeries = new CategorySeries(
					"My spendings");
			for (int i = 0; i < amounts.size(); i++) {
				String aditionalInfo = WalletConstants.SPACE + amounts.get(i) 
				+ WalletConstants.SPACE
				+ WalletConstants.CURRENCY_CODE;
				
				distributionSeries.add(categories.get(i) + aditionalInfo,
						amounts.get(i));
			}
			// Instantiating a renderer for the Pie Chart
			DefaultRenderer defaultRenderer = new DefaultRenderer();
			for (int i = 0; i < amounts.size(); i++) {
				SimpleSeriesRenderer seriesRenderer = new SimpleSeriesRenderer();
				seriesRenderer.setColor(colors[i]);
				defaultRenderer.addSeriesRenderer(seriesRenderer);
			}
			defaultRenderer.setChartTitle(chartTitle);
			defaultRenderer.setChartTitleTextSize(getChartTitleTextSize());
			defaultRenderer.setZoomButtonsVisible(true);
			
			chartView = ChartFactory.getPieChartView(getActivity(), distributionSeries, defaultRenderer);
			layout.addView(chartView);
			charts.put(entity.getType(), chartView);
		}
	}
	
	private void fetchDataForPieChart(Entity entity) {
		Category category = new Category();
		category.setType(entity.getType());
		List<String> allCategories = categoryTransaction.read(category);
		amounts =  new ArrayList<Double>();
		categories = new ArrayList<String>();
		for (String item : allCategories) {								
			double amountPerCategory = computeAmountPerCategory(walletTransaction
					.readPerCategory(item));
			if (amountPerCategory > 0.0) {
				categories.add(item);
				amounts.add(amountPerCategory);
			}
		}
	}
	
	private void configureLineChart(Entity entity) {
		layout.removeAllViews();
		
		if (charts.containsKey(entity.getType())) {
			chartView = charts.get(entity.getType());
			layout.addView(chartView);
		} else {
			fetchDataForLineChart();
		
			XYSeries budgetEvolution = new XYSeries("Budget");
			List<Double> budgetAmounts = new ArrayList<Double>(budget.values());
			for (int i = 0; i < budget.size(); i++) {
				budgetEvolution.add(i, budgetAmounts.get(i));
			}
			
			XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
			dataset.addSeries(budgetEvolution);

			// Configure how chart line will look
			XYSeriesRenderer renderer = new XYSeriesRenderer();
			renderer.setColor(Color.LTGRAY);
			renderer.setPointStyle(PointStyle.CIRCLE);
			renderer.setFillPoints(true);
			renderer.setLineWidth(2);
			renderer.setDisplayChartValues(true);

			// Configure how whole chart will look
			XYMultipleSeriesRenderer multiRenderer = new XYMultipleSeriesRenderer();
			multiRenderer.setXLabels(0);
			multiRenderer.setChartTitle("Budget evolution");
			multiRenderer.setChartTitleTextSize(getChartTitleTextSize());
			multiRenderer.setXTitle("Transaction Date");
			multiRenderer.setYTitle("Amount");
			multiRenderer.setZoomButtonsVisible(true);

			List<String> budgetTransactionDate = new ArrayList<String>(
					budget.keySet());
			for (int i = 0; i < budget.size(); i++) {
				multiRenderer
						.addXTextLabel(i, budgetTransactionDate.get(i));
			}
			multiRenderer.addSeriesRenderer(renderer);

			chartView = ChartFactory.getLineChartView(
					getActivity().getBaseContext(), dataset, multiRenderer);
			layout.addView(chartView);
			charts.put(entity.getType(), chartView);
		}
	}
	
	private void fetchDataForLineChart() {		
		budget = budgetTransaction.readAll();
	}

	private Double computeAmountPerCategory(List<Double> amounts) {
		if (amounts.size() == 0) {
			return 0.0;
		} else {
			double amountPerCategory = 0.0;
			for (Double amount : amounts) {
				amountPerCategory += amount;
			}
			return amountPerCategory;
		}
	}
	
	private float getChartTitleTextSize() {
		return 27.0f;
	}
	
	private void showAlertDialog(String title, String message) {		
		AlertDialog.Builder alertDialogBuilder = 
			new AlertDialog.Builder(getView().getContext());
		
		alertDialogBuilder.setTitle(title);
		alertDialogBuilder.setMessage(message);
		alertDialogBuilder.setNegativeButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog,int id) {
				dialog.cancel();
			}
		});
		AlertDialog alertDialog = alertDialogBuilder.create();
		alertDialog.show();
	}
}
